package com.motong.gongdan.config.auth;


import com.motong.gongdan.entity.User;
import com.motong.gongdan.util.LoginUtil;
import com.motong.gongdan.util.RedisUtil;
import com.motong.gongdan.util.StringUtil;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import javax.xml.bind.DatatypeConverter;
import java.util.Date;
import java.util.Objects;

/**
 * @Auther: FreddieFang
 * @Date: 2021/11/10 19:22
 * @Description:
 */
@Slf4j
public class JwtConfig {

    private static String SECRET_KEY = "GD-USER";
    private static String SECRET_KEY_H5 = "GD-USER-H5";
    private static final long EXPIRE_TIME = 60 * 60 * 1000;

    public static String getToken(User user, String type) {
        String redisToken = null;
        if ("h5".equals(type)) {
            redisToken = (String) RedisUtil.get("JWT-TOKEN-U-H5" + user.getAccount());
            if (StringUtil.isNotBlank(redisToken)) {
//                RedisUtil.set("JWT-TOKEN-U-H5" + user.getAccount(), redisToken, EXPIRE_TIME);
                return redisToken;
            }
        } else {
            redisToken = (String) RedisUtil.get("JWT-TOKEN-U" + user.getAccount());
            if (StringUtil.isNotBlank(redisToken)) {
//                RedisUtil.set("JWT-TOKEN-U" + user.getAccount(), redisToken, EXPIRE_TIME);
                return redisToken;
            }
        }
        Date nowDate = new Date();
        Date date = new Date(System.currentTimeMillis() + (EXPIRE_TIME * 1000));
        String token = null;
        if (type.equals("h5")) {
            date = new Date(System.currentTimeMillis() + (EXPIRE_TIME * 100000));
            token = Jwts.builder()
                    .setHeaderParam("typ", "JWT")
                    .setSubject(user.getAccount())
                    .setIssuedAt(nowDate)
                    .setExpiration(date)
                    .signWith(SignatureAlgorithm.HS512, SECRET_KEY_H5)
                    .compact();
            RedisUtil.set("JWT-TOKEN-U-H5" + user.getAccount(), token);
            RedisUtil.set("user-h5:" + user.getAccount(), user.getFactoryId());
            RedisUtil.set("user-h5-factory-code:" + user.getAccount(), user.getFactoryCode());
        } else {
            token = Jwts.builder()
                    .setHeaderParam("typ", "JWT")
                    .setSubject(user.getAccount())
                    .setIssuedAt(nowDate)
                    .setExpiration(date)
                    .signWith(SignatureAlgorithm.HS512, SECRET_KEY)
                    .compact();
            RedisUtil.set("JWT-TOKEN-U" + user.getAccount(), token, EXPIRE_TIME);
            RedisUtil.set("user-admin:" + user.getAccount(), user.getFactoryId());
            RedisUtil.set("user-admin-factory-code:" + user.getAccount(), user.getFactoryCode());
        }

        LoginUtil.setLoginUserFactory(user.getFactoryId());
        LoginUtil.setLoginUserToken(token);
        LoginUtil.setLoginAccount(user.getAccount());
        LoginUtil.setLoginUserId(user.getId());
        return token;
    }

    /*
     * 获取 Token 中注册信息
     */
    public static String getTokenUserAccount(String token, String type) {
        if (!StringUtils.hasLength(token)) {
            return null;
        }
        Claims claims = null;
        try {
            if (type.equals("h5")) {
                claims = Jwts.parser().setSigningKey(SECRET_KEY_H5).parseClaimsJws(token).getBody();
            } else {
                claims = Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();
            }
            return claims.getSubject();
        } catch (Exception e) {
//            claims = e.getClaims();
            log.error("根据token获取用户异常!");
            return null;
        }
    }

    // 验证 token 是否过期
    public static Boolean isTokenExpired(String token, String type) {
        try {
            Claims claims = getClaimsFromToken(token, type);
            Date expiration = claims.getExpiration();
            // 当前的时间在 expiration 时间之前时，返回 false，也就是 token 还未过期
            return expiration.before(new Date());
        } catch (ExpiredJwtException e) {
            e.getClaims();
            return true;
        }
    }

    public static Claims getClaimsFromToken(String token, String type) {
        Claims claims = null;
        try {
            if (type.equals("h5")) {
                claims = Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary("GD-USER-H5")).parseClaimsJws(token)
                        .getBody();
            } else {
                claims = Jwts.parser().setSigningKey(DatatypeConverter.parseBase64Binary(SECRET_KEY)).parseClaimsJws(token)
                        .getBody();
            }
        } catch (ExpiredJwtException e) {
            e.getClaims();
        }
        return claims;
    }

    // 校验令牌
    public static Boolean validateToken(String token, String type) {
        String redisToken = null;
        if ("h5".equals(type)) {
            redisToken = (String) RedisUtil.get("JWT-TOKEN-U-H5" + getTokenUserAccount(token, type));
        } else {
            Object temp = RedisUtil.get("JWT-TOKEN-U" + getTokenUserAccount(token, type));
            redisToken = Objects.isNull(temp) ? "" : temp.toString();
        }
        if (StringUtil.isBlank(token)) {
            return false;
        }
        if (StringUtil.isBlank(redisToken)) {
            return false;
        }
        if (!redisToken.equals(token)) {
            return false;
        }
        Claims claimsFromToken = getClaimsFromToken(token, type);
        return (null != claimsFromToken && !isTokenExpired(token, type));
    }

}
